package utils

import (
	"fmt"
	"github.com/cavaliergopher/grab/v3"
	"github.com/gogf/gf/frame/g"
	"github.com/gomodule/redigo/redis"
	"io"
	"io/fs"
	"log"
	"math/rand"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"time"

	"github.com/gogf/gf/util/gconv"
	"github.com/tealeg/xlsx"
)

type Account struct {
	Email    string
	Password string
}

var Accounts []Account

var UsedAccounts []Account

func IsHttpHref(href string) bool {
	reg := regexp.MustCompile(`^http://|https://`)
	if reg.Match(gconv.Bytes(href)) {
		return true
	} else {
		return false
	}
}

func RandomSleep() {
	time.Sleep(time.Duration(rand.Intn(15)+15) * time.Second)
}

// 获取当前时间自然周
func WeekTime(title string) string {
	now := time.Now()
	weekStart := now.AddDate(0, 0, -int(now.Weekday())+1)
	weekEnd := weekStart.AddDate(0, 0, 6)
	weektime := fmt.Sprintf("%d.%02d.%02d-%d.%02d.%02d", weekStart.Year(), weekStart.Month(), weekStart.Day(), weekEnd.Year(), weekEnd.Month(), weekEnd.Day())
	driverPath := g.Cfg().GetString("download.path")
	isExist, path, err := CheckFileExist(driverPath, title)
	if isExist == true && err == nil {
		return path
	} else {
		reg := regexp.MustCompile(`[\\/:*?"<>|]`)
		title = reg.ReplaceAllString(title, "_")
		folderName := filepath.Join(driverPath, weektime, title)
		// 创建文件夹
		err = os.MkdirAll(folderName, os.ModePerm)
		if err != nil {
			fmt.Println("创建文件夹失败:", err)
		}
		return folderName
	}

}

// 判断文件夹是否存在

func CheckFileExist(root string, fileName string) (bool, string, error) {
	// 遍历文件夹
	found := false
	cPath := ""
	err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}

		// 检查是否为指定名称的文件夹
		if d.Name() == fileName {
			found = true
			if err != nil {
				return err
			}
			//fmt.Println("path:", path)
			cPath = path
		}

		return nil
	})

	if err != nil {
		return false, cPath, err
	}

	return found, cPath, nil
}

func GetTitleFromUrl(url string) string {
	// 使用字符串操作截取最后的名字
	res := strings.Split(url, "videos/")
	if len(res) > 1 {
		name := strings.Trim(res[1], "/")
		//fmt.Println("Name:", name)

		return name
	} else {
		fmt.Println("Invalid URL.")
		return ""
	}
}

func IsFileDownloading(filename string) bool {
	RandomSleep()

	fmt.Println("filename:", filename)
	file_len := len(filename)
	fmt.Println("file_len:", file_len)
	bb := filename[file_len-10:]
	fmt.Println("bb:", bb)

	if strings.Contains(filename[len(filename)-10:], "crdownload") {
		fmt.Println("aa:", filename[len(filename)-10:])

	}

	return len(filename) >= 10 && filename[len(filename)-10:] == "crdownload"
}

// 初始化的时候加载

func LoadAccount() {
	// 从配置文件中读取账号列表
	accountList := g.Cfg().GetArray("account_list")
	for _, account := range accountList {
		accountMap := account.(map[string]interface{})
		email := accountMap["email"].(string)
		password := accountMap["password"].(string)
		SetAccountToRedis(email, password)
	}
}

func LoadAccountFromExcel() {
	// 从配置文件中读取账号列表
	accountPath := g.Cfg().GetString("account_excel.path")

	excelFile, err := xlsx.OpenFile(accountPath)
	if err != nil {
		log.Fatal(err)
	}
	var accountList []Account

	for _, sheet := range excelFile.Sheets {
		for _, row := range sheet.Rows {
			// 获取 A 列的值
			cellA := row.Cells[0].String()
			// 获取 B 列的值
			cellB := row.Cells[1].String()

			accountList = append(accountList, Account{Email: cellA, Password: cellB})
			SetAccountToRedis(cellA, cellB)

		}
	}

	//fmt.Println("accountList:", accountList)
}

// 随机获取一个账号

func GetAccounts() {

	if len(Accounts) == 0 {
		// 清空 UsedAccounts
		UsedAccounts = nil

		conn := g.Redis().Conn()
		defer conn.Close()
		values, err := redis.StringMap(conn.Do("HGETALL", PIXABAY_ACCOUNT_REDIS))

		if err != nil {
			fmt.Println("获取ACCOUNT列表失败", err)
			log.Fatal("无账号可用")
		}

		// 将值转换为 []Account 类型
		Accounts = make([]Account, 0, len(values))
		for key, value := range values {
			var account Account
			account.Email = key
			account.Password = value
			Accounts = append(Accounts, account)
		}

	}

	//fmt.Println("Accounts:", Accounts)
}

func RandAccount() *Account {
	GetAccounts()

	//fmt.Println("Accounts:", Accounts)
	//fmt.Println("UsedAccounts:", UsedAccounts)

	// 使用第一个账号
	account := Accounts[0]
	fmt.Println("使用账号:", account)

	// 将已使用的账号从 Accounts 中删除，并添加到 UsedAccounts 中
	Accounts = Accounts[1:]
	UsedAccounts = append(UsedAccounts, account)

	//fmt.Println("Accounts:", Accounts)
	//fmt.Println("UsedAccounts:", UsedAccounts)
	return &account
}

func CountFiles(dir string) (int, error) {
	count := 0

	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if !info.IsDir() {
			count++
		}

		return nil
	})

	if err != nil {
		return 0, err
	}

	return count, nil
}

func ClearDir(filePath string) error {

	err := os.RemoveAll(filePath)
	if err != nil {
		fmt.Println("无法清空目录:", err)
		return err
	}

	err = os.MkdirAll(filePath, os.ModePerm)
	if err != nil {
		fmt.Println("无法重新创建目录:", err)
		return err
	}

	fmt.Println("目录内容已清空")
	return nil
}

func Unique(urls []string) []string {

	// 使用map[string]bool进行去重
	uniqueURLs := make(map[string]bool)
	for _, url := range urls {
		uniqueURLs[url] = true
	}

	// 将去重后的URL放入新的切片
	var deduplicatedURLs []string
	for url := range uniqueURLs {
		deduplicatedURLs = append(deduplicatedURLs, url)
	}
	var result []string
	// 打印去重后的URL
	for _, url := range deduplicatedURLs {
		result = append(result, url)
	}
	return result
}

// 用grab下载
func DownloadImageGrab(url, filename string) error {
	// 打开日志文件
	file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	// 设置日志输出到文件
	log.SetOutput(file)

	client := grab.NewClient()
	req, err := grab.NewRequest(".", url)
	if err != nil {
		fmt.Println(err)
		log.Println(err)

		return err
	}
	req.Filename = filename
	resp := client.Do(req)

	if err := resp.Err(); err != nil {
		fmt.Println(err)
		log.Println(err)

		return err
	}
	fmt.Printf("Download saved to %v\n", resp.Filename)

	// start UI loop
	t := time.NewTicker(500 * time.Millisecond)
	defer t.Stop()

	return nil
}

func CheckDownloadUrl(url string) (bool, string) {
	substr := "https://s3.eu-west-1.amazonaws.com/"

	index := strings.Index(url, substr)
	if index != -1 {
		split := strings.Split(url, "?")
		filename := strings.SplitN(split[0], "/", -1)[len(strings.SplitN(split[0], "/", -1))-1]

		fmt.Println("文件名:", filename)
		return true, filename
	} else {
		fmt.Println("字符串中不包含指定的子字符串")
		return false, ""
	}
}

// GetVideo 下载文件并保存到本地
func GetVideo(filepath string, url string) error {
	response, err := http.Get(url)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	file, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = io.Copy(file, response.Body)
	if err != nil {
		return err
	}

	return nil
}

//
//func GetAccountsssss() {
//
//	conn := g.Redis().Conn()
//	defer conn.Close()
//	accountList, err := conn.Do("HKEYS", PIXABAY_ACCOUNT_REDIS)
//
//	if err != nil {
//		fmt.Println("获取ACCOUNT列表失败", err)
//	}
//
//	// 创建已使用账号的列表
//	usedAccounts := make([]string, 0)
//
//	for {
//		// 从 Redis 哈希表中获取账号列表
//		//accountList, err := client.HKeys("account_hash").Result()
//		//if err != nil {
//		//	fmt.Println("获取账号列表失败:", err)
//		//	return
//		//}
//
//		// 从账号列表中排除已使用的账号
//		availableAccounts := excludeUsedAccounts(accountList, usedAccounts)
//
//		// 检查是否还有可用账号
//		if len(availableAccounts) == 0 {
//			fmt.Println("没有可用账号")
//			break
//		}
//
//		// 随机选择一个账号
//		rand.Seed(time.Now().UnixNano())
//		randomIndex := rand.Intn(len(availableAccounts))
//		selectedAccount := availableAccounts[randomIndex]
//
//		// 使用选中的账号进行操作
//		fmt.Println("使用账号:", selectedAccount)
//
//		// 在此处执行你的方法逻辑
//
//		// 将已使用的账号添加到列表中
//		usedAccounts = append(usedAccounts, selectedAccount)
//
//		// 在循环结束时，将已使用的账号从列表中移除
//		defer func(account string) {
//			usedAccounts = removeUsedAccount(usedAccounts, account)
//		}(selectedAccount)
//
//		// 在此处添加循环的终止条件
//		// 如果不需要终止循环，可以删除此处的条件判断
//		//if condition {
//		//	break
//		//}
//	}
//}

//// 排除已使用的账号
//func excludeUsedAccounts(accounts []string, usedAccounts []string) []string {
//	availableAccounts := make([]string, 0)
//
//	for _, account := range accounts {
//		if !contains(usedAccounts, account) {
//			availableAccounts = append(availableAccounts, account)
//		}
//	}
//
//	return availableAccounts
//}
//
//// 检查切片中是否包含指定元素
//func contains(slice []string, element string) bool {
//	for _, item := range slice {
//		if item == element {
//			return true
//		}
//	}
//	return false
//}
//
//// 从切片中移除指定元素
//func removeUsedAccount(accounts []string, account string) []string {
//	index := -1
//
//	for i, item := range accounts {
//		if item == account {
//			index = i
//			break
//		}
//	}
//
//	if index >= 0 {
//		accounts = append(accounts[:index], accounts[index+1:]...)
//	}
//
//	return accounts
//}
